package cn.blnp.net.flowable.boot.localize.dynamic.jump.subflow;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ExecutionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <h3>动态跳转与子流程的结合案例</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/6/18 15:08
 */
@Slf4j
@SpringBootTest
public class DynamicJumpSubFlowTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private IdentityService identityService;
    @Resource
    private TaskService taskService;

    SimplePropertyPreFilter taskFilter = new SimplePropertyPreFilter(Task.class, "id",
            "name", "executionId", "taskDefinitionKey", "assignee", "owner");
    SimplePropertyPreFilter executionFilter = new SimplePropertyPreFilter(Execution.class,
            "id", "parentId", "processInstanceId", "activityId", "isScope");

    /**
     *  <h1>子流程案例的动态跳转</h1>
     *  该案例里有两个嵌入式子流程、一个事件子流程构成，在流程发起后根据信号来触发事件子流程的执行
     *      <ul>
     *          <li><b>流程定义文件：</b>{@link flow/subProcessDynamicJumpProcess.bpmn20.xml}</li>
     *          <li>
     *              <b>流程预览图：</b></br>
     *              <img src="https://cdn4.winhlb.com/2025/06/18/6852692681774.png" >
     *          </li>
     *      </ul>
     **/
    @Test
    public void test() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("flow/subProcessDynamicJumpProcess.bpmn20.xml")
                .name("动态跳转基础案例")
                .deploy();
        //流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        log.info("流程定义ID：{}", processDefinition.getId());

        //启动流程实例
        ProcessInstance procInst = runtimeService.startProcessInstanceById(processDefinition.getId());
        log.info("流程实例ID：{}", procInst.getId());
        TaskQuery taskQuery = taskService.createTaskQuery()
                .processInstanceId(procInst.getId());
        ExecutionQuery executionQuery = runtimeService.createExecutionQuery()
                .processInstanceId(procInst.getId());

        Task task1 = taskQuery.singleResult();
        log.info("第一次跳转前，当前任务为：{}", JSON.toJSONString(task1, taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        //在事件子流程EventSubProcess1内部从StartEvent4跳转到UserTask8、UserTask9
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(procInst.getId())
                .moveSingleActivityIdToActivityIds("startEvent4",
                        Arrays.asList("task8", "task9"))
                .changeState();
        log.info("第一次跳转后，当前任务为：{}", JSON.toJSONString(taskQuery.list(), taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        //在事件子流程EventSubProcess1内部UserTask8、UserTask9跳转到UserTask10
        List<Task> taskList1 = taskQuery.list().stream()
                .filter(t -> t.getTaskDefinitionKey().equals("task8")
                        || t.getTaskDefinitionKey().equals("task9"))
                .collect(Collectors.toList());
        List<String> executionList1 = taskList1.stream()
                .map(Task::getExecutionId).collect(Collectors.toList());
        runtimeService.createChangeActivityStateBuilder()
                .moveExecutionsToSingleActivityId(executionList1, "task10")
                .changeState();
        log.info("第二跳转后，当前任务为：{}", JSON.toJSONString(taskQuery.list(), taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        //从事件子流程EventSubProcess1的UserTask10跳转到子流程SubProcess1的UserTask3、SubProcess2的
        //UserTask6
        Task task10 = taskQuery.list().stream()
                .filter(t -> t.getTaskDefinitionKey().equals("task10"))
                .findFirst().get();
        runtimeService.createChangeActivityStateBuilder()
                .moveSingleExecutionToActivityIds(task10.getExecutionId(),
                        Arrays.asList("task3", "task6"))
                .changeState();
        log.info("第三次跳转后，当前任务为：{}", JSON.toJSONString(taskQuery.list(), taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        //从子流程SubProcess1的UserTask3、SubProcess2的UserTask6跳转到主流程的ParallelGateway2
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(procInst.getId())
                .moveActivityIdsToSingleActivityId(Arrays.asList("task3", "task6"),
                        "parallelGateway2")
                .changeState();
        log.info("第四次跳转后，当前任务为：{}", JSON.toJSONString(taskQuery.list(), taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        //完成任务task2
        Task task2 = taskQuery.list().stream()
                .filter(t -> t.getTaskDefinitionKey().equals("task2"))
                .findFirst().get();
        taskService.complete(task2.getId());
        //从主流程的UserTask1跳转到主流程的UserTask2
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(procInst.getId())
                .moveActivityIdTo("task1", "task2")
                .changeState();
        log.info("第五次跳转后，当前任务为：{}", JSON.toJSONString(taskQuery.list(), taskFilter));
        log.info("当前执行实例有：{}", JSON.toJSONString(executionQuery.list(), executionFilter));

        /**
         *  演示结果：
         *  2025-06-18 15:36:09.891  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 流程定义ID：subProcessDynamicJumpProcess:1:210004
         * 2025-06-18 15:36:09.974  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 流程实例ID：210005
         * 2025-06-18 15:36:10.244  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第一次跳转前，当前任务为：{"executionId":"210006","id":"210012","name":"UserTask1","taskDefinitionKey":"task1"}
         * 2025-06-18 15:36:10.278  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task1","id":"210006","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"startEvent4","id":"210008","isScope":false,"parentId":"210005","processInstanceId":"210005"}]
         * 2025-06-18 15:36:10.325  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第一次跳转后，当前任务为：[{"executionId":"210006","id":"210012","name":"UserTask1","taskDefinitionKey":"task1"},{"executionId":"210013","id":"210016","name":"UserTask8","taskDefinitionKey":"task8"},{"executionId":"210014","id":"210018","name":"UserTask9","taskDefinitionKey":"task9"}]
         * 2025-06-18 15:36:10.328  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task1","id":"210006","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"task8","id":"210013","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"task9","id":"210014","isScope":false,"parentId":"210005","processInstanceId":"210005"}]
         * 2025-06-18 15:36:10.410  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第二跳转后，当前任务为：[{"executionId":"210006","id":"210012","name":"UserTask1","taskDefinitionKey":"task1"},{"executionId":"210019","id":"210021","name":"UserTask10","taskDefinitionKey":"task10"}]
         * 2025-06-18 15:36:10.413  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task1","id":"210006","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"task10","id":"210019","isScope":false,"parentId":"210005","processInstanceId":"210005"}]
         * 2025-06-18 15:36:10.537  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第三次跳转后，当前任务为：[{"executionId":"210006","id":"210012","name":"UserTask1","taskDefinitionKey":"task1"},{"executionId":"210026","id":"210029","name":"UserTask3","taskDefinitionKey":"task3"},{"executionId":"210027","id":"210031","name":"UserTask6","taskDefinitionKey":"task6"}]
         * 2025-06-18 15:36:10.541  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task1","id":"210006","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"subProcess1","id":"210022","isScope":true,"parentId":"210005","processInstanceId":"210005"},{"activityId":"subProcess2","id":"210024","isScope":true,"parentId":"210005","processInstanceId":"210005"},{"activityId":"task3","id":"210026","isScope":false,"parentId":"210022","processInstanceId":"210005"},{"activityId":"task6","id":"210027","isScope":false,"parentId":"210024","processInstanceId":"210005"}]
         * 2025-06-18 15:36:10.603  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第四次跳转后，当前任务为：[{"executionId":"210006","id":"210012","name":"UserTask1","taskDefinitionKey":"task1"},{"executionId":"210033","id":"210038","name":"UserTask2","taskDefinitionKey":"task2"}]
         * 2025-06-18 15:36:10.606  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task1","id":"210006","isScope":false,"parentId":"210005","processInstanceId":"210005"},{"activityId":"task2","id":"210033","isScope":false,"parentId":"210005","processInstanceId":"210005"}]
         * 2025-06-18 15:36:10.665  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 第五次跳转后，当前任务为：[{"executionId":"210041","id":"210043","name":"UserTask2","taskDefinitionKey":"task2"}]
         * 2025-06-18 15:36:10.669  INFO 63364 --- [           main] c.b.n.f.b.l.d.j.s.DynamicJumpSubFlowTest : 当前执行实例有：[{"id":"210005","isScope":true,"processInstanceId":"210005"},{"activityId":"task2","id":"210041","isScope":false,"parentId":"210005","processInstanceId":"210005"}]
         **/
    }
}
